package ch.cryptobox.serivces;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;

import org.acplt.oncrpc.OncRpcException;

import belisarius.sss.SSSByte;
import ch.cryptobox.filehandles.FileHandleI;
import ch.cryptobox.filehandles.MultiFileHandle;
import ch.cryptobox.nfsError.CreateFileException;
import ch.cryptobox.nfsError.FileNotFoundException;
import ch.cryptobox.nfsError.ReadWriteException;

public class SSSEncryptionSyncronizationService implements MultiServerSynchronizationService {

	private final ArrayList<SynchronizationService> services;
	private final int n;
	private final int[] ids;
	private final SSSByte sss;

	public SSSEncryptionSyncronizationService(final  ArrayList<SynchronizationService> services) {
		this.services = services;
		n=services.size();
		sss=new SSSByte();

		ids=new int[n];

		for(int i=0;i<n;++i)
			ids[i]=i+1;
	}


	public void addFile(final File file, final byte[] data) throws OncRpcException, IOException, CreateFileException, ReadWriteException, FileNotFoundException {
		//System.out.println(SSSEncryptionSyncronizationService.class.getName() + ".addFile() Called");

		final ByteBuffer src=ByteBuffer.allocate(data.length);
		src.put(data);
		src.rewind();

		final ByteBuffer[] dst = new ByteBuffer[n];
		for(int i=0;i<n;++i)
			dst[i]=ByteBuffer.allocate(data.length);

		sss.split(data.length, src, n, ids, dst);

		for(int i=0;i<n;++i)
			services.get(i).addFile(file, dst[i].array());
	}



	public void addDirectory(final File file) throws OncRpcException, IOException,
	CreateFileException, ReadWriteException, FileNotFoundException {
		for(final SynchronizationService s : services)
			s.addDirectory(file);
	}

	public byte[] readFile(final MultiFileHandle fileHandle) throws OncRpcException,
	IOException, ReadWriteException {
		final ArrayList<FileHandleI> handles = fileHandle.getHandles();


		final ByteBuffer[] src=new ByteBuffer[n];

		byte[] data= handles.get(0).download();//services.get(0).readFile(fileHandle);
		final int length=data.length;
		src[0]=ByteBuffer.allocate(length);
		src[0].put(data);
		src[0].rewind();



		for(int i=1;i<n;++i){
			data= handles.get(i).download();//services.get(i).readFile(fileHandle);

			src[i]=ByteBuffer.allocate(length);
			src[i].put(data);
			src[i].rewind();
		}
		final ByteBuffer dst=ByteBuffer.allocate(length);
		sss.join(length, ids, src, dst);
		return dst.array();
	}



	@Override
	public FileHandleI getRootHandle() {
		final MultiFileHandle handle = new MultiFileHandle(this);
		for(final SynchronizationService s : services) {
			handle.addHandle(s.getRootHandle());
		}

		return handle;
	}

}
